package com.ywu.container.standard.service.frpc;

import com.ywu.boot.exception.YwuRuntimeException;
import com.ywu.container.standard.config.AppConfig;
import com.ywu.container.standard.util.SSHUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.*;
import java.lang.reflect.Field;
import java.util.*;

/**
 * @ClassName ParseFrpcInI
 * @Description 解析FRPC配置文件
 * @Author GroundDemo
 * @Date 2024/7/13 16:52
 * @Version 1.0
 **/
@Component
@Slf4j
public class ParseFrpcInI {
    @Autowired
    private AppConfig appConfig;

    /**
    * @Author GroundDemo
    * @Description 解析服务器上的frpc配置文件
    * @Date 18:06 2024/7/13
    * @Param []
    * @return java.util.Map<java.lang.String,com.ywu.container.standard.service.frpc.FrpcIniObj>
    **/
    public Map<String, FrpcIniObj> parseFrpcIni() throws Exception {
        BufferedReader bufferedReader = null;
        // 存储返回结果
        HashMap<String, FrpcIniObj> resMap = new HashMap<>();
        File file = new File(appConfig.getFrpcLocalFilePath() + "/" + appConfig.getFrpcFileName());
        boolean res = SSHUtils.downloadFile(appConfig.getSshHost(), appConfig.getSshPort(), appConfig.getSshUserName(),
                appConfig.getSshPassword(), appConfig.getFrpcFilePath(), appConfig.getFrpcFileName(),
                appConfig.getFrpcLocalFilePath(), appConfig.getFrpcFileName());
        if (!res) {
            throw new YwuRuntimeException("parse Frpc Error");
        }
        // 按行读取文件
        bufferedReader = new BufferedReader(new FileReader(file));
        String line;
        String frpcNameKey = "";
        while ((line = bufferedReader.readLine()) != null) {
            if (line.startsWith("[") && line.endsWith("]")) {
                frpcNameKey = line.substring(1, line.length() - 1);
                FrpcIniObj frpcIniObj = new FrpcIniObj();
                frpcIniObj.setFrpcName(frpcNameKey);
                resMap.put(frpcNameKey, frpcIniObj);
                continue;
            }
            // 获取map中的对象
            FrpcIniObj frpcIniObj = resMap.get(frpcNameKey);
            // 去除空格
            String lineRes = line.replaceAll(" ", "");
            // 根据等号分割
            String[] split = lineRes.split("=");
            if (split.length != 2) {
                log.warn("parseFrpcIni split is ERROR!!");
                continue;
            }
            // 根据字段设置值
            String frpcParamName = split[0];
            String frpcParamValue = split[1];
            Class<? extends FrpcIniObj> frpcIniObjClass = frpcIniObj.getClass();
            Field field = frpcIniObjClass.getDeclaredField(frpcParamName);
            field.setAccessible(true);
            field.set(frpcIniObj, frpcParamValue);
        }
        try {
            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 删除文件
        boolean delete = file.delete();
        if (!delete) {
            log.warn("File delete error {}", file.getName());
        }
        return resMap;
    }

    /**
    * @Author GroundDemo
    * @Description 重写服务器上的FRPC配置文件
    * @Date 18:06 2024/7/13
    * @Param []
    * @return void
    **/
    public void reWriteFrpcIni(Map<String, FrpcIniObj> parseFrpcMap) throws IOException, IllegalAccessException {
        File file = new File(appConfig.getFrpcLocalFilePath() + "/" + appConfig.getFrpcFileName());
        FileWriter fileWriter = new FileWriter(file);
        Set<String> keys = parseFrpcMap.keySet();
        for (String key : keys) {
            FrpcIniObj value = parseFrpcMap.get(key);
            // 反射写入文件
            Class<? extends FrpcIniObj> frpcIniObjClass = value.getClass();
            Field[] declaredFields = frpcIniObjClass.getDeclaredFields();
            for (Field field : declaredFields) {
                field.setAccessible(true);
                // 如果字段值不为空，设置值
                Object obj = field.get(value);
                if (Objects.nonNull(obj)) {
                    if (field.getName().equals("frpcName")) {
                        fileWriter.write("[" + obj + "]\n");
                    } else {
                        fileWriter.write(field.getName() + " = " + obj + "\n");
                    }
                }
            }
            fileWriter.write("\n");
        }
        fileWriter.flush();
        // 上传文件
        SSHUtils.uploadFile(appConfig.getSshHost(), appConfig.getSshPort(), appConfig.getSshUserName(),
                appConfig.getSshPassword(), appConfig.getFrpcFilePath(), appConfig.getFrpcFileName(),
                appConfig.getFrpcLocalFilePath(), appConfig.getFrpcFileName());
    }

    /**
    * @Author GroundDemo
    * @Description 重启frpc客户端
    * @Date 18:29 2024/7/13
    * @Param []
    * @return void
    **/
    public void reloadFrpc() {
        // 执行重启命令
        String cmd = "cd " + appConfig.getFrpcFilePath() + ";" + "./frpc reload";
        try {
            SSHUtils.execCommand(appConfig.getSshHost(), appConfig.getSshPort(), appConfig.getSshUserName(),
                    appConfig.getSshPassword(), cmd);
        } catch (Exception e) {
            log.error("reload frpc error {}", e.getMessage());
            throw new YwuRuntimeException("reload frpc error");
        }
    }

    /**
    * @Author GroundDemo
    * @Description 查询当前frpc已运行的接口映射关系
    * @Date 20:34 2024/7/13
    * @Param []
    * @return java.util.List<com.ywu.container.standard.service.frpc.FrpcStatusEntity>
    **/
    public List<FrpcStatusEntity> queryFrpcInstance() {
        // 存储返回值
        ArrayList<FrpcStatusEntity> resList = new ArrayList<>();
        String cmd = "cd " + appConfig.getFrpcFilePath() + ";" + "./frpc status";
        String res = null;
        try {
            res = SSHUtils.execCommand(appConfig.getSshHost(), appConfig.getSshPort(), appConfig.getSshUserName(),
                    appConfig.getSshPassword(), cmd);
        } catch (Exception e) {
            log.error("exec frpc status error {}", e.getMessage());
            throw new YwuRuntimeException("exec frpc status error");
        }
        // 按行分割
        String[] split = res.split("\n");
        // 记录当前数据的协议类型
        String type = "";
        // 遍历并解析数据
        for (String line : split) {
            // 根据空格分割
            String[] lineSplit = line.split(" ");
            if (lineSplit.length == 2 || lineSplit.length == 0) {
                continue;
            }
            if (lineSplit.length == 1) {
                type = lineSplit[0];
                continue;
            }
            if (lineSplit[0].equals("Name")) {
                continue;
            }
            // 做一个标志位，执行到哪个标志就给哪个字段设置值
            int index = 0;
            FrpcStatusEntity frpcStatusEntity = new FrpcStatusEntity();
            frpcStatusEntity.setType(type);
            // 遍历单行结果
            for (String s : lineSplit) {
                if (StringUtils.isBlank(s)) {
                    continue;
                }
                if (index == 0) {
                    frpcStatusEntity.setName(s);
                } else if (index == 1) {
                    frpcStatusEntity.setStatus(s);
                } else if (index == 2) {
                    frpcStatusEntity.setLocalAddr(s);
                } else if (index == 3) {
                    frpcStatusEntity.setRemoteAddr(s);
                }
                index++;
            }
            resList.add(frpcStatusEntity);
        }
        return resList;
    }
}
